package com.jmb.waimao.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jmb.waimao.entity.EmailAddress;
import com.jmb.waimao.entity.SocialMediaUser;
import com.jmb.waimao.mapper.SocialMediaUserMapper;
import com.jmb.waimao.service.EmailAddressService;
import com.jmb.waimao.service.SocialMediaUserService;
import com.jmb.waimao.util.SocialMediaCrawler;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVPrinter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * Service implementation for SocialMediaUser
 */
@Service
@Slf4j
public class SocialMediaUserServiceImpl extends ServiceImpl<SocialMediaUserMapper, SocialMediaUser> implements SocialMediaUserService {

    @Autowired
    private EmailAddressService emailAddressService;
    
    @Autowired
    private SocialMediaCrawler socialMediaCrawler;

    @Override
    public List<SocialMediaUser> crawlFacebookUsers(List<String> keywords, int maxUsers) {
        log.info("Crawling Facebook users with keywords: {}, max users: {}", keywords, maxUsers);
        List<SocialMediaUser> users = socialMediaCrawler.crawlFacebook(keywords, maxUsers);
        
        // Save users to database
        if (!users.isEmpty()) {
            LocalDateTime now = LocalDateTime.now();
            users.forEach(user -> {
                user.setCreateTime(now);
                user.setUpdateTime(now);
                user.setDeleted(0);
            });
            
            saveBatch(users);
            log.info("Saved {} Facebook users to database", users.size());
        }
        
        return users;
    }

    @Override
    public List<SocialMediaUser> crawlInstagramUsers(List<String> keywords, int maxUsers) {
        log.info("Crawling Instagram users with keywords: {}, max users: {}", keywords, maxUsers);
        List<SocialMediaUser> users = socialMediaCrawler.crawlInstagram(keywords, maxUsers);
        
        // Save users to database
        if (!users.isEmpty()) {
            LocalDateTime now = LocalDateTime.now();
            users.forEach(user -> {
                user.setCreateTime(now);
                user.setUpdateTime(now);
                user.setDeleted(0);
            });
            
            saveBatch(users);
            log.info("Saved {} Instagram users to database", users.size());
        }
        
        return users;
    }

    @Override
    public List<SocialMediaUser> crawlTwitterUsers(List<String> keywords, int maxUsers) {
        log.info("Crawling Twitter users with keywords: {}, max users: {}", keywords, maxUsers);
        List<SocialMediaUser> users = socialMediaCrawler.crawlTwitter(keywords, maxUsers);
        
        // Save users to database
        if (!users.isEmpty()) {
            LocalDateTime now = LocalDateTime.now();
            users.forEach(user -> {
                user.setCreateTime(now);
                user.setUpdateTime(now);
                user.setDeleted(0);
            });
            
            saveBatch(users);
            log.info("Saved {} Twitter users to database", users.size());
        }
        
        return users;
    }

    @Override
    public Page<SocialMediaUser> getUsersByPlatform(String platform, int page, int size) {
        Page<SocialMediaUser> pageRequest = new Page<>(page, size);
        LambdaQueryWrapper<SocialMediaUser> queryWrapper = new LambdaQueryWrapper<>();
        
        queryWrapper.eq(SocialMediaUser::getDeleted, 0);
        
        if (platform != null && !platform.isEmpty()) {
            queryWrapper.eq(SocialMediaUser::getPlatform, platform);
        }
        
        queryWrapper.orderByDesc(SocialMediaUser::getCreateTime);
        
        return page(pageRequest, queryWrapper);
    }

    @Override
    public byte[] exportUsersToCsv(String platform) {
        try (ByteArrayOutputStream out = new ByteArrayOutputStream();
             OutputStreamWriter writer = new OutputStreamWriter(out, StandardCharsets.UTF_8)) {
            
            // Define CSV headers
            String[] headers = {
                "ID", "Username", "Display Name", "Email", "Phone Number", "Platform",
                "Profile URL", "Bio", "Location", "Followers", "Following", "Posts"
            };
            
            // Create CSV printer
            CSVPrinter csvPrinter = new CSVPrinter(writer, CSVFormat.DEFAULT.withHeader(headers));
            
            // Query users
            LambdaQueryWrapper<SocialMediaUser> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(SocialMediaUser::getDeleted, 0);
            
            if (platform != null && !platform.isEmpty()) {
                queryWrapper.eq(SocialMediaUser::getPlatform, platform);
            }
            
            // Get all users
            List<SocialMediaUser> users = list(queryWrapper);
            
            // Write users to CSV
            for (SocialMediaUser user : users) {
                csvPrinter.printRecord(
                    user.getId(),
                    user.getUsername(),
                    user.getDisplayName(),
                    user.getEmail(),
                    user.getPhoneNumber(),
                    user.getPlatform(),
                    user.getProfileUrl(),
                    user.getBio(),
                    user.getLocation(),
                    user.getFollowersCount(),
                    user.getFollowingCount(),
                    user.getPostsCount()
                );
            }
            
            csvPrinter.flush();
            return out.toByteArray();
            
        } catch (IOException e) {
            log.error("Error exporting users to CSV", e);
            throw new RuntimeException("Failed to export users to CSV", e);
        }
    }

    @Override
    public Map<String, Long> getStatisticsByPlatform() {
        LambdaQueryWrapper<SocialMediaUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SocialMediaUser::getDeleted, 0);
        
        List<SocialMediaUser> users = list(queryWrapper);
        
        // Group users by platform and count
        Map<String, Long> statistics = users.stream()
            .collect(Collectors.groupingBy(SocialMediaUser::getPlatform, Collectors.counting()));
        
        return statistics;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int convertToEmailAddresses(List<Long> userIds, String groupName) {
        if (userIds == null || userIds.isEmpty()) {
            return 0;
        }
        
        // Get users by IDs
        List<SocialMediaUser> users = listByIds(userIds);
        
        // Filter users with valid email addresses
        List<SocialMediaUser> usersWithEmail = users.stream()
            .filter(user -> user.getEmail() != null && !user.getEmail().isEmpty())
            .collect(Collectors.toList());
        
        if (usersWithEmail.isEmpty()) {
            return 0;
        }
        
        // Convert to email addresses
        List<EmailAddress> emailAddresses = new ArrayList<>();
        LocalDateTime now = LocalDateTime.now();
        
        for (SocialMediaUser user : usersWithEmail) {
            EmailAddress emailAddress = new EmailAddress();
            emailAddress.setEmail(user.getEmail());
            emailAddress.setName(user.getDisplayName() != null ? user.getDisplayName() : user.getUsername());
            emailAddress.setGroupName(groupName);
            emailAddress.setRemark("Imported from " + user.getPlatform() + " user: " + user.getUsername());
            emailAddress.setCreateTime(now);
            emailAddress.setUpdateTime(now);
            emailAddress.setDeleted(0);
            
            emailAddresses.add(emailAddress);
        }
        
        // Save email addresses
        emailAddressService.saveBatch(emailAddresses);
        
        return emailAddresses.size();
    }
}
